【问题标题】:Angular url plus sign converting to space角网址加号转换为空格
【发布时间】:2018-01-07 18:58:22
【问题描述】:

我有角度应用程序,我想在查询字符串中传递加号 +,例如:

http://localhost:3000/page?name=xyz+manwal

当我点击此 URL 时,它会转换为:

http://localhost:3000/page?name=xyz%20manwal

其中 %20 指的是空格 。如何防止这种转换?

【问题讨论】:

  • 你为什么需要那个?
  • 我想在给定的 URL 中使用像 xyz+manwal 这样的名称值,目前它正在保存 xyz manwal
  • 它只是一个 URL,无论你在哪里阅读它都应该被正确地解析为加号,你不能在 URL 中使用加号。阅读this
  • @Maximus 我尝试解码并使用它。我得到空间``而不是+。有一个旧版本的网站正在运行,它采用.net 技术。有 + 号是可以接受的,但在有角度的新版本中是不行的。因此,两者都必须遵循相同的 URL 模式。
  • 使用十六进制代码作为加号,因为+ 相当于网址中的%20

标签: javascript angular url


【解决方案1】:

您可以通过添加修复此问题的拦截器来覆盖默认角度编码:

import { HttpInterceptor, HttpRequest, HttpEvent, HttpHandler, HttpParams, HttpParameterCodec } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Observable } from "rxjs";

@Injectable()
export class EncodeHttpParamsInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const params = new HttpParams({encoder: new CustomEncoder(), fromString: req.params.toString()});
    return next.handle(req.clone({params}));
  }
}


class CustomEncoder implements HttpParameterCodec {
  encodeKey(key: string): string {
    return encodeURIComponent(key);
  }

  encodeValue(value: string): string {
    return encodeURIComponent(value);
  }

  decodeKey(key: string): string {
    return decodeURIComponent(key);
  }

  decodeValue(value: string): string {
    return decodeURIComponent(value);
  }
}

并在 app.module.ts 的 providers 部分声明它

providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: EncodeHttpParamsInterceptor,
      multi: true
    }
]

【讨论】:

  • 这会造成双重编码的混乱
  • 供参考:这是一个bug,见github.com/angular/angular/issues/11058
  • 引用的 CustomEncoder 类可以在 github.com/angular/angular/issues/18261 中找到,该类写于 21/10/2017 (Orestes)
  • 这个解决方案对我有用。我现在可以在将请求从 Angular (8) 发送到 Java (8) 时保留 '+' 登录 url 查询参数。它没有转换为 " " 或 %2B
【解决方案2】:

这是一个常见问题。 URL 使用+ 字符来分隔两个单词。为了在参数值中使用+ 字符,您需要先对参数值进行编码,然后再将它们添加为 URL 的一部分。 Javascript / TypeScript 为该特定目的提供了一个 encodeURI() 函数。

URL 编码将字符转换为可以传输的格式 通过互联网。 [w3Schools Reference]

以下是解决此问题的方法:

let encodedName = encodeURI('xyz+manwal');
let encodedURI = 'http://localhost:3000/page?name='+encodedName;

//.. OR using string interpolation
let encodedURI = `http://localhost:3000/page?name=${ encodedName }`;

同样的,你可以使用decodeURI()方法解码参数。

let decodedValue = decodeURI(encodedValue);

【讨论】:

  • 这个解决方案更好,在 URL 中使用之前的编码效果很好,但是。有第 3 方生成链接,其中包含 + 符号。这些 URL 在 c# 的旧版本应用程序中运行良好。但是对于我们(应用程序的新版本)来说,它甚至不接受 + 立即将 + 转换为 %20 的符号。
  • 当我使用 webpack 提供 Angular 时,它会将 URL + 更改为 %20。我想查看+ 登录 URL。在 apache php 的其他服务器中,没有将 + 转换为 URL 中相同的任何内容。
【解决方案3】:

在 Angular 5.2.7+ 中,查询字符串中的“+”被替换为空格“”。

这里是对应的提交:fix(router): fix URL serialization

如果您想更改此行为并将“+”替换为“%2B”,您可以创建自定义 url 序列化程序并在 AppModule 提供程序中提供它。

import { DefaultUrlSerializer, UrlSerializer, UrlTree } from '@angular/router';

export default class CustomUrlSerializer implements UrlSerializer {
    private _defaultUrlSerializer: DefaultUrlSerializer = new DefaultUrlSerializer();

    parse(url: string): UrlTree {
        // Encode "+" to "%2B"
        url = url.replace(/\+/gi, '%2B');
        // Use the default serializer.
        return this._defaultUrlSerializer.parse(url);
    }

    serialize(tree: UrlTree): string {
        return this._defaultUrlSerializer.serialize(tree).replace(/\+/gi, '%2B');
    }
}

@NgModule({
    imports: [
        BrowserModule,
        BrowserAnimationsModule,
        AppRoutingModule
    ],
    declarations: [
        AppComponent
    ],
    providers: [
        { provide: UrlSerializer, useClass: CustomUrlSerializer }
    ],

    entryComponents: [],
    bootstrap: [AppComponent]
})
export class AppModule {
}

http://localhost:3000/page?name=xyz+manwal

网址将被转换为:

http://localhost:3000/page?name=xyz%2Bmanwal

希望这会有所帮助。

【讨论】:

  • 谢谢!这应该是 Angular v5.2.7+ 的选择答案
【解决方案4】:

在 Angular v6.1.10 中,如果您只需要在一个地方修复“+”号编码,这对我有用。

getPerson(data: Person) {

  const httpParams = new HttpParams({
    fromObject: {
      id: data.id,
      name: data.name,
      other: "xyz+manwal"
    }
  });

  // manually encode all "+" characters from the person details
  let url = BASE_URL + "/select?" + httpParams.toString().replace(/\+/gi, '%2B');

  return this.http.get(url);
}

我发现如果您在初始化httpParams 对象时尝试替换“+”号,它不起作用。将httpParams 转换为字符串后必须进行替换,如下行所示:

let url = BASE_URL + "/select?" + httpParams.toString().replace(/\+/gi, '%2B');

【讨论】:

  • 感谢上帝!这对我有用!我想知道为什么 HttpParams 上的设置不起作用
【解决方案5】:

这是一个很常见的问题。您可以在 application/x-www-form-urlencoded 请求中正常传递它。没有其他请求能够正确解析 +。他们总是将其解析为 %20 而不是 %2B。

您需要手动操作查询参数,有两种方法:

  • 将参数编码为 base64 编码,这样没有特殊字符可以破坏您的应用程序,但您还需要在接收部分处理它(解码)。
  • 更简单的解决方案是,在点击 URL 之前,将所有 + 符号替换为 %2B。这样对方就可以正常解码,不需要特殊的程序。

有关更多信息,您应该参考以下堆栈溢出问题Android: howto parse URL String with spaces to URI object?URL encoding the space character: + or %20?

【讨论】:

    【解决方案6】:

    我正在使用 Angular 7,+(这个“xyz+manwal”)被替换为 URI 中的 空格(比如这个“xyz manwal”)当它到达后端代码时。

    encodeURI() 对我不起作用,我使用 encodeURIComponent()+ 转换为 %2B

         encodeURIComponent("xyz+manwal") => "xyz%2Bmanwal"
    

    下面是示例代码

        // filter = xyz+manwal
        let filterString =  encodeURIComponent(filter); // filterString = xyz%2Bmanwal
    
        return this.http.get<ListResults>("http://website/query-results?" + filterString ).pipe(
          retry(3),
          catchError(........)
        )
    

    【讨论】:

      【解决方案7】:

      我找到了解决方案并将其发布以供将来参考。 Angular js 将+ 符号转换为%2B

      以下代码阻止了这种情况:

      .config([
          '$provide', function($provide) {
            $provide.decorator('$browser', function($delegate) {
              let superUrl = $delegate.url;
              $delegate.url = (url, replace) => {
                if(url !== undefined) {
                  return superUrl(url.replace(/\%2B/g,"+"), replace);
                } else {
                  return superUrl().replace(/\+/g,"%2B");
                }
              };
              return $delegate;
            });
          }
        ])
      

      【讨论】:

      • 关于如何实现此代码的任何想法。我正在尝试用 + 号替换 %20。
      • @SebastianSALAMANCA 您可以在您的app.module 中添加此config
      • 我做到了,但是当我在 url 中键入“嘿你”时,角度会将其转换为 %20
      • 正确的行为空间将始终解码为“%20”。但是当你输入 + 时,它不会转换成“%20”。
      【解决方案8】:

      使用new HttpUrlEncodingCodec().encodeValue("+91")

      【讨论】:

        猜你喜欢
        • 2016-10-23
        • 1970-01-01
        • 2012-09-08
        • 1970-01-01
        • 2020-10-19
        • 2023-03-19
        • 2012-05-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多