我正在开发一个应用程序来上传。las文件到铯离子。
我已经修改了这个代码https://github.com/CesiumGS/cesium-ion-rest-api-examples/blob/main/tutorials/rest-api/index.js从浏览器传递一个文件。
当我在我的本地环境中运行npm start时,它工作得很完美。
当我在应用引擎上尝试同样的事情时,我没有得到关于进程在哪里的消息。它确实上传了文件。我只是无法监控正在发生的事情。
为了解释下面发生的事情,我从客户端发送一个文件,然后它被app.post("/upload"
捕获然后,它在Ion上创建资产,然后上传到S3,然后它告诉Ion它完成了,然后它监视Ion上的平铺。然后我每秒钟调用一次app.post("/progress"
,这是将事物的状态发送回客户端。
我想我可能错过了一个逻辑,一些我完全错误的基本的东西。我使用一个服务的后端和前端。这是问题的一部分吗?
const express = require('express');
const app = express();
const port = process.env.PORT || 3001;
const fileUpload = require("express-fileupload");
const cors = require('cors');
var path = require('path');
const AWS = require('aws-sdk');
const fs = require('fs');
const rawdatafr = require('./lang/fr.json');
const rawdataen = require('./lang/en.json');
const axios = require('axios').default;
const accessToken = process.env.REACT_APP_ION_TOKEN;
const environment = process.env.NODE_ENV || 'production';
var urlLang = (environment === 'development') ? 'client/src/lang/' : 'lang/';
console.log('urlLang ? '+urlLang);
app.use(cors());
app.use(fileUpload({
useTempFiles: true,
safeFileNames: false,
preserveExtension: true,
tempFileDir: 'temp/'
}));
'use strict';
var messageFromLoc = rawdataen;
var input = null;
var filename = null;
var srcType = 'POINT_CLOUD';
var message = null;
var needMonitoring = false;
var assetMetadata = null;
var finished = null;
function resetGlobalvar(){
message = null;
needMonitoring = false;
assetMetadata = null;
finished = null;
input = null;
filename = null;
srcType = 'POINT_CLOUD';
}
async function creat_asset(){
finished = false;
message = 'create asset';
axios.post('https://api.cesium.com/v1/assets', {
name: filename,
description: '',
type: '3DTILES',
options: {
position:[ 2.29, 48.85, 0.1],
sourceType: srcType,
}
},{
headers: { Authorization: `Bearer ${accessToken}` }
})
.then(function (response) {
message = 'created successfully :> send to s3';
sendtos3(response.data);
})
.catch(function (error) {
console.log(error);
message = error;
});
}
async function sendtos3(response){
console.log('Asset created.');
message = 'send to s3';
try{
const uploadLocation = response.uploadLocation;
const s3 = new AWS.S3({
apiVersion: '2006-03-01',
region: 'us-east-1',
signatureVersion: 'v4',
endpoint: uploadLocation.endpoint,
credentials: new AWS.Credentials(
uploadLocation.accessKey,
uploadLocation.secretAccessKey,
uploadLocation.sessionToken)
});
let params = {
Body: fs.createReadStream(input),
Bucket: uploadLocation.bucket,
Key: uploadLocation.prefix+filename
};
let s3Response = await s3.upload(params).on('httpUploadProgress', function (progress) {
message = `${messageFromLoc.upload}: ${((progress.loaded / progress.total) * 100).toFixed(2)}%`;
console.log(`Upload: ${((progress.loaded / progress.total) * 100).toFixed(2)}%`);
}).promise();
// request successed
console.log(`File uploaded to S3 at ${s3Response.Bucket} bucket. File location: ${s3Response.Location}`);
message = `File uploaded to S3 at ${s3Response.Bucket} bucket. File location: ${s3Response.Location}`;
step3(response);
// return s3Response.Location;
}
// request failed
catch (ex) {
console.error(ex);
message = ex;
}
}
async function step3(response){
const onComplete = response.onComplete;
assetMetadata = response.assetMetadata;
message = 'step3';
axios.post(onComplete.url, onComplete.fields,{
headers: { Authorization: `Bearer ${accessToken}` }
})
.then(function (response) {
message = 'step3 done';
monitorTiling(assetMetadata);
})
.catch(function (error) {
console.log(error);
message = error;
});
}
async function monitorTiling(assetMetadata){
// console.log(response);
const assetId = assetMetadata.id;
message = 'monitorTiling';
axios.get(`https://api.cesium.com/v1/assets/${assetId}`,{headers: { Authorization: `Bearer ${accessToken}` }})
.then(function (response) {
// handle success
console.log('monitorTiling - success');
var status = response.data.status;
message = 'Tiling - success';
if (status === 'COMPLETE') {
console.log('Asset tiled successfully');
console.log(`View in ion: https://cesium.com/ion/assets/${assetMetadata.id}`);
message = 'Asset tiled successfully';
needMonitoring = false;
finished = true;
} else if (status === 'DATA_ERROR') {
console.log('ion detected a problem with the uploaded data.');
message = 'ion detected a problem with the uploaded data.';
needMonitoring = false;
finished = true;
} else if (status === 'ERROR') {
console.log('An unknown tiling error occurred, please contact support@cesium.com.');
message = 'An unknown tiling error occurred, please contact support@cesium.com.';
needMonitoring = false;
finished = true;
} else {
needMonitoring = true;
if (status === 'NOT_STARTED') {
console.log('Tiling pipeline initializing.');
message = 'Tiling pipeline initializing.';
} else { // IN_PROGRESS
console.log(`Asset is ${assetMetadata.percentComplete}% complete.`);
message = `Asset is ${assetMetadata.percentComplete}% complete.`;
}
}
})
.catch(function (error) {
// handle error
console.log(error);
message =error;
})
}
/*------- LISTEN FOR CALL TO UPLOAD AND START THE UPLOAD PROCESS ----------*/
app.post("/upload", (req, res) => {
if (!req.files) {
res.send("File was not found");
message = 'File was not found';
return;
}
input = req.files.file.tempFilePath;
filename = req.files.file.name;
emptyTempFolder('temp', input.replace('temp/', ''));
var ext = path.extname(filename);
if(ext=='.zip'){
srcType = 'CITYGML';
}
/*------- START UPLOAD PROCESS ----------*/
creat_asset();
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
/*------- LISTEN FOR PROGRESS TO UPLOAD ASSET ----------*/
app.get("/progress", (req, res) => {
// lang = req.get('Accept-Language').substring(0, 2).toLowerCase();
// if(lang=='fr'){
// messageFromLoc = rawdatafr;
// }
console.log('message ='+message);
if(needMonitoring){
monitorTiling(assetMetadata);
}
res.json({ message: message, done: finished, myAssetMetadata: assetMetadata });
if(finished){
resetGlobalvar();
}
});
/*--------------STATIC ----------------*/
app.use(express.static( path.join(__dirname, 'build' )));
我的app。yaml是这样的:
runtime: nodejs14
env: standard
includes:
- env_variables.yaml
instance_class: B1
service: my-app
basic_scaling:
max_instances: 25
idle_timeout: 60m
我想这是从你的实例。您正在使用最多25个实例的基本扩展。
看起来像是下列情况的组合
a)当你向/progress
发送请求时,你的应用程序的一个新实例被创建,这意味着所有的全局变量都是从它们的默认值开始的(消息的初始值是null
)。
/progress
的请求由一个已经在处理上传请求的现有实例处理,并且该请求已经完成,因此消息显示completed
在本地环境中没有这个问题,因为只有一个实例在运行。
要测试这个理论,修改你的app.yaml
并设置max_instances: 1
。这应该强制应用程序只使用一个实例,这意味着后续请求应该使用一个现有的实例(它具有全局变量的更新状态)