diff --git a/.env b/.env
index d73f21df..2c2aaa9c 100644
--- a/.env
+++ b/.env
@@ -5,7 +5,10 @@
# The IP below should be swapped to your real IP or DNS name, like 192.168.88.248, etc. if testing from remote browsers or mobile devices
ESHOP_EXTERNAL_DNS_NAME_OR_IP=localhost
-
+MINIO_PORT=9100
+MINIO_CONSOLE_PORT=9101
+MINIO_ROOT_USER=root
+MINIO_ROOT_PASSWORD=admin123
# If the NAMESPACE env var is set, Dapr does not load any
# component that does not specify the same namespace.
NAMESPACE=eshop
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index c47ba2d1..ac1f2553 100644
--- a/.gitignore
+++ b/.gitignore
@@ -374,4 +374,22 @@ MigrationBackup/
**/tempkey.rsa
# macOS files
-.DS_Store
\ No newline at end of file
+.DS_Store
+/src/ApiGateways/Aggregators/Web.Shopping.HttpAggregator/.aspnet/DataProtection-Keys/key-26c59856-9ff6-469a-8a7c-d954f1b1669b.xml
+/src/Services/Basket/Basket.API/.aspnet/DataProtection-Keys/key-c48680ef-d1e0-4988-9486-e0f1bfb2f268.xml
+/src/Services/Identity/Identity.API/.aspnet/DataProtection-Keys/key-986ee17b-ff21-4a99-8917-f348faa16819.xml
+/src/Services/Identity/Identity.API/keys/is-signing-key-EAA68BA13C0497676FE6C8154E4CB60D.json
+/src/Services/Identity/Identity.API/keys/is-signing-key-C773B66C065AB0FF099B1FA96A8DA508.json
+/src/Services/Identity/Identity.API/keys/is-signing-key-C13A9A73D69887B49EE224B7610EE44B.json
+/src/Services/Identity/Identity.API/keys/is-signing-key-A146395E40C2B5665F0A76377B3E49BC.json
+/src/Services/Identity/Identity.API/keys/is-signing-key-9C9A36C9FFCF89F1ED6BA432240C2E8C.json
+/src/Services/Identity/Identity.API/keys/is-signing-key-6DDC6082EC29A1BB9CE5AD77483AF126.json
+/src/Services/Identity/Identity.API/keys/is-signing-key-511F2270F9ECDA692F2CD351C2E3FD8A.json
+/src/Services/Identity/Identity.API/keys/is-signing-key-3E93D8BFF96E2B87F1278BF88CC89461.json
+/src/Services/Identity/Identity.API/keys/is-signing-key-245BE88025479B3CBC04D33D8F04B6DB.json
+/src/Services/Identity/Identity.API/keys/is-signing-key-23AFA9F9104D9AA570D6C4771A65ABFA.json
+/src/Services/Identity/Identity.API/keys/is-signing-key-22B27C69702109C30DDF13C5E8E156D8.json
+/src/Services/Ordering/Ordering.API/.aspnet/DataProtection-Keys/key-b0c35976-b46c-41ab-8f3a-710334bfb345.xml
+/src/Web/BlazorClient.Host/.aspnet/DataProtection-Keys/key-5495f7e4-a7fb-4723-a26b-613c3969fb3f.xml
+/minio/data/.minio.sys/buckets/.minio.sys/buckets
+/minio/data
diff --git a/dapr/components/eshop-pubsub.yaml b/dapr/components/eshop-pubsub.yaml
index f4235d45..715798ee 100644
--- a/dapr/components/eshop-pubsub.yaml
+++ b/dapr/components/eshop-pubsub.yaml
@@ -8,7 +8,7 @@ spec:
version: v1
metadata:
- name: host
- value: "amqp://rabbitmq:5672"
+ value: "amqp://rabbitmq:4672"
- name: durable
value: "false"
- name: deletedWhenUnused
diff --git a/docker-compose.override.yml b/docker-compose.override.yml
index 2e809122..3f3b9ee0 100644
--- a/docker-compose.override.yml
+++ b/docker-compose.override.yml
@@ -6,6 +6,18 @@ version: '3.4'
# but values present in the environment vars at runtime will always override those defined inside the .env file
services:
+ minio:
+ restart: always
+ command: ["minio", "server", "--console-address", ":9001", "/data"]
+ volumes:
+ - ./minio/data:/data
+ - ./minio/config:/root/.minio
+ ports:
+ - "9100:9000"
+ - "9101:9001"
+ environment:
+ - MINIO_ROOT_USER=${MINIO_ROOT_USER}
+ - MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}
maildev:
ports:
@@ -13,7 +25,7 @@ services:
rabbitmq:
ports:
- - "5672:5672"
+ - "4672:5672"
redis:
image: redis:alpine
@@ -31,7 +43,7 @@ services:
- SA_PASSWORD=Pass@word
- ACCEPT_EULA=Y
ports:
- - "5433:1433"
+ - "2433:1433"
volumes:
- eshop-sqldata:/var/opt/mssql
@@ -76,6 +88,10 @@ services:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80
- RetryMigrations=true
+ - Minio__Endpoint=minio:9000
+ - Minio__SecretKey=${MINIO_ROOT_PASSWORD}
+ - Minio__BucketName=eshop-catalog
+ - Minio__AccessKey=${MINIO_ROOT_USER}
- SeqServerUrl=http://seq
# Temporarily while waiting for https://github.com/dapr/dotnet-sdk/issues/779 to get fixed.
- ConnectionStrings__CatalogDB=Server=sqldata;Database=Microsoft.eShopOnDapr.Services.CatalogDb;User Id=sa;Password=Pass@word;TrustServerCertificate=true
diff --git a/docker-compose.yml b/docker-compose.yml
index f3fd556a..f818a51a 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -2,6 +2,9 @@ version: '3.4'
services:
+ minio:
+ image: minio/minio
+
maildev:
image: maildev/maildev
diff --git a/docs/media/zipkin-WEBSHOPPINGAPIGW.png b/docs/media/zipkin-WEBSHOPPINGAPIGW.png
new file mode 100644
index 00000000..6ecd68c2
Binary files /dev/null and b/docs/media/zipkin-WEBSHOPPINGAPIGW.png differ
diff --git a/src/ApiGateways/Envoy/envoy.yaml b/src/ApiGateways/Envoy/envoy.yaml
index 511e988d..ea44ef00 100644
--- a/src/ApiGateways/Envoy/envoy.yaml
+++ b/src/ApiGateways/Envoy/envoy.yaml
@@ -31,12 +31,19 @@ static_resources:
allow_headers: "authorization, content-type, x-requestid, x-requested-with, x-signalr-user-agent"
allow_credentials: true
routes:
+ - name: "x-pics"
+ match:
+ prefix: "x/c/pics/"
+ route:
+ auto_host_rewrite: true
+ prefix_rewrite: "x/pics/"
+ cluster: catalog
- name: "pics"
match:
prefix: "/c/pics/"
route:
auto_host_rewrite: true
- prefix_rewrite: "/pics/"
+ prefix_rewrite: "/api/v1/catalog/img/" #http://192.168.1.5:5202/c/pics/10.jpeg
cluster: catalog
- name: "c-short"
match:
diff --git a/src/Services/Catalog/Catalog.API/Catalog.API.csproj b/src/Services/Catalog/Catalog.API/Catalog.API.csproj
index b00a09fd..98331833 100644
--- a/src/Services/Catalog/Catalog.API/Catalog.API.csproj
+++ b/src/Services/Catalog/Catalog.API/Catalog.API.csproj
@@ -20,6 +20,7 @@
+
all
diff --git a/src/Services/Catalog/Catalog.API/Controllers/MediaController.cs b/src/Services/Catalog/Catalog.API/Controllers/MediaController.cs
new file mode 100644
index 00000000..3b27fc62
--- /dev/null
+++ b/src/Services/Catalog/Catalog.API/Controllers/MediaController.cs
@@ -0,0 +1,88 @@
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using System.ComponentModel.DataAnnotations;
+using System.IO;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Options;
+using Minio;
+using Minio.DataModel;
+using System.Collections.Generic;
+
+namespace Microsoft.eShopOnDapr.Services.Catalog.API.Controllers
+{
+ public class MediaController : Controller
+ {
+ IConfiguration Config { get; }
+ protected IOptionsMonitor OptionsMonitor { get; }
+ public MediaController(IConfiguration config)
+ {
+ Config = config;
+ }
+
+ ///
+ /// 上传疵点图片
+ ///
+ ///
+ ///
+ [HttpPost]
+ [Route("/api/v1/catalog/upload")]
+ public async Task Upload([Required] IFormFile file)
+ {
+ if (file != null && file.Length < 1)
+ {
+ }
+ string endpoint = Config["Minio:Endpoint"];
+ string accessKey = Config["Minio:AccessKey"];
+ string secretKey = Config["Minio:SecretKey"];
+ string bucketName = Config["Minio:BucketName"];
+ string domainHost = Config["Host"];
+ MinioClient minio = new MinioClient()
+ .WithEndpoint(endpoint)
+ .WithCredentials(accessKey, secretKey)
+ .Build();
+ using (Stream stream = file.OpenReadStream())
+ {
+ Dictionary metaData = new Dictionary
+ {
+ { "Name", $"{file.Name}" }
+ };
+ PutObjectArgs args = new PutObjectArgs()
+ .WithBucket(bucketName)
+ .WithObject(file.FileName)
+ .WithStreamData(stream)
+ .WithObjectSize(stream.Length)
+ .WithContentType("application/octet-stream")
+ .WithHeaders(metaData);
+ await minio.PutObjectAsync(args);
+ return Json(new { });
+ }
+ }
+ ///
+ /// http://192.168.1.5:5101/api/v1/catalog/img/10.jpeg
+ ///
+ ///
+ ///
+ [HttpGet]//
+ [Route("/api/v1/catalog/img/{objectName}")]
+ public async Task GetFileAsync(string objectName = "hello.jpg")
+ {
+ string endpoint = Config["Minio:Endpoint"];
+ string accessKey = Config["Minio:AccessKey"];
+ string secretKey = Config["Minio:SecretKey"];
+ var bucketName = Config["Minio:BucketName"];
+ string fileName = Path.Combine(Directory.GetCurrentDirectory(), objectName);
+
+ MinioClient minio = new MinioClient()
+ .WithEndpoint(endpoint)
+ .WithCredentials(accessKey, secretKey)
+ .Build();
+ GetObjectArgs getObjectArgs = new GetObjectArgs()
+ .WithBucket(bucketName)
+ .WithObject(objectName)
+ .WithFile(fileName);
+ ObjectStat stat = await minio.GetObjectAsync(getObjectArgs);
+ return new PhysicalFileResult(fileName, stat.ContentType);
+ }
+ }
+}